home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / packer / ha0999beta / src / archive.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  10KB  |  412 lines

  1. /***********************************************************************
  2.   This file is part of HA, a general purpose file archiver.
  3.   Copyright (C) 1995 Harri Hirvola
  4.  
  5.   This program is free software; you can redistribute it and/or modify
  6.   it under the terms of the GNU General Public License as published by
  7.   the Free Software Foundation; either version 2 of the License, or
  8.   (at your option) any later version.
  9.  
  10.   This program is distributed in the hope that it will be useful,
  11.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.   GNU General Public License for more details.
  14.  
  15.   You should have received a copy of the GNU General Public License
  16.   along with this program; if not, write to the Free Software
  17.   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ************************************************************************
  19.     HA archive handling
  20. ***********************************************************************/
  21.  
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include "error.h"
  26. #include "ha.h"
  27. #include "archive.h"
  28. #include "haio.h"
  29.  
  30. #define STRING    32
  31.  
  32. int arcfile=-1;
  33. char *arcname=NULL;
  34. struct stat arcstat;
  35. static unsigned arccnt=0;
  36. static int dirty=0,addtries;
  37. static U32B nextheader=4,thisheader,arcsize,bestpos,trypos;
  38. static Fheader newhdr;
  39.  
  40. static U32B getvalue(int len) {
  41.  
  42.     unsigned char buf[4];
  43.     U32B val;
  44.     int i;
  45.     
  46.     if (read(arcfile,buf,len)!=len) error(1,ERR_READ,arcname);
  47.     for (val=i=0;i<len;++i) val|=(U32B)buf[i]<<(i<<3);
  48.     return val;
  49. }
  50.  
  51. static void putvalue(U32B val, int len) {
  52.  
  53.     unsigned char buf[4];
  54.     int i;
  55.     
  56.     for (i=0;i<len;++i,val>>=8) buf[i]=(unsigned char) val&0xff;
  57.     if (write(arcfile,&buf,len)!=len) error(1,ERR_WRITE,arcname);
  58. }
  59.  
  60. static char *getstring(void) {
  61.     
  62.     char *sptr;
  63.     int offset;
  64.     
  65.     if ((sptr=malloc(STRING))==NULL) error(1,ERR_MEM,"getstring()");
  66.     for (offset=0;;offset++) {
  67.     if (read(arcfile,sptr+offset,1)!=1) error(1,ERR_READ,arcname);
  68.     if (sptr[offset]==0) break;
  69.     if ((offset&(STRING-1))==(STRING-1)) {
  70.         if ((sptr=realloc(sptr,offset+STRING))==NULL) 
  71.           error(1,ERR_MEM,"getstring()");
  72.     }
  73.     }
  74.     return sptr;
  75. }
  76.  
  77. static void putstring(char *string) {
  78.     
  79.     int len;
  80.  
  81.     len=strlen(string)+1;
  82.     if (write(arcfile,string,len)!=len) error(1,ERR_WRITE,arcname);
  83. }
  84.  
  85. static Fheader *getheader(void) {
  86.  
  87.     static Fheader hd={0,0,0,0,0,0,NULL,NULL,0};
  88.  
  89.     if ((hd.ver=getvalue(1))!=0xff) {
  90.     hd.type=hd.ver&0xf;
  91.     hd.ver>>=4;
  92.     if (hd.ver>MYVER) error(1,ERR_TOONEW);
  93.     if (hd.ver<LOWVER) error(1,ERR_TOOOLD);
  94.     if (hd.type!=M_SPECIAL && hd.type!=M_DIR && hd.type>=M_UNK) 
  95.       error(1,ERR_UNKMET,hd.type);
  96.     }
  97.     hd.clen=getvalue(4);
  98.     hd.olen=getvalue(4);
  99.     hd.crc=getvalue(4);
  100.     hd.time=getvalue(4);
  101.     if (hd.path!=NULL) free(hd.path);
  102.     hd.path=getstring();
  103.     if (hd.name!=NULL) free(hd.name);
  104.     hd.name=getstring();
  105.     hd.mdilen=(unsigned)getvalue(1);
  106.     hd.mylen=hd.mdilen+20+strlen(hd.path)+strlen(hd.name);
  107.     md_gethdr(hd.mdilen,hd.type);
  108.     return &hd;
  109. }
  110.  
  111. static void putheader(Fheader *hd) {
  112.  
  113.     putvalue((hd->ver<<4)|hd->type,1);
  114.     putvalue(hd->clen,4); 
  115.     putvalue(hd->olen,4); 
  116.     putvalue(hd->crc,4); 
  117.     putvalue(hd->time,4); 
  118.     putstring(hd->path);
  119.     putstring(hd->name);
  120.     putvalue(hd->mdilen,1);
  121.     md_puthdr();
  122. }    
  123.  
  124. static void arc_clean(void) {
  125.  
  126.     U32B ipos,opos,cpylen;
  127.     int len;
  128.     unsigned cnt;
  129.     Fheader *hd;
  130.     
  131.     ipos=opos=4;
  132.     for (cnt=arccnt;cnt;--cnt) {
  133.     if (lseek(arcfile,ipos,SEEK_SET)<0) error(1,ERR_SEEK,"arc_clean()");
  134.     for (;;) {
  135.         hd=getheader();
  136.         if (hd->ver!=0xff) break;
  137.         ipos+=hd->clen+hd->mylen;
  138.         if (lseek(arcfile,ipos,SEEK_SET)<0) 
  139.           error(1,ERR_SEEK,"arc_clean()");
  140.     } 
  141.     if (ipos==opos) ipos=opos+=hd->clen+hd->mylen;
  142.     else {
  143.         cpylen=hd->clen+hd->mylen;
  144.         while (cpylen) {
  145.         if (lseek(arcfile,ipos,SEEK_SET)<0) 
  146.           error(1,ERR_SEEK,"arc_clean()");
  147.         len=read(arcfile,ib,BLOCKLEN>cpylen?(unsigned)cpylen:BLOCKLEN);
  148.         if (len<=0) error(1,ERR_READ,arcname);
  149.         cpylen-=len;
  150.         ipos+=len;
  151.         if (lseek(arcfile,opos,SEEK_SET)<0) 
  152.           error(1,ERR_SEEK,"arc_clean()");
  153.         if (write(arcfile,ib,len)!=len) error(1,ERR_WRITE,arcname);
  154.         opos+=len;
  155.         }
  156.     }
  157.     }
  158.     md_truncfile(arcfile,opos);
  159. }
  160.  
  161. void arc_close(void) {
  162.     
  163.     if (arcfile>=0) {
  164.     if (dirty) arc_clean();
  165.     close(arcfile);
  166.     if (!arccnt) {
  167.         if (remove(arcname)) error(1,ERR_REMOVE,arcname);
  168.     }
  169.     }
  170. }
  171.  
  172. static U32B arc_scan(void) {
  173.     
  174.     U32B pos;
  175.     unsigned i;
  176.     Fheader *hd;
  177.     
  178.     pos=4;
  179.     for (i=0;i<arccnt;++i) {
  180.     if (pos>=arcsize) {
  181.         error(0,ERR_CORRUPTED);
  182.         arccnt=i;
  183.         return pos;
  184.     }
  185.     if (lseek(arcfile,pos,SEEK_SET)<0) error(1,ERR_SEEK,"arc_seek()");
  186.     hd=getheader();
  187.     pos+=hd->clen+hd->mylen;
  188.     if (hd->ver==0xff) {
  189.         dirty=1;
  190.         --i;
  191.     }
  192.     }
  193.     if (pos!=arcsize) dirty=1;
  194.     return pos;
  195. }
  196.  
  197. void arc_open(char *aname,int mode) {
  198.     
  199.     char id[2];
  200.     
  201.     dirty=0;
  202.     arcname=md_arcname(aname);
  203.     if ((arcfile=open(arcname,(mode&ARC_RDO)?AO_RDOFLAGS:AO_FLAGS))>=0) {
  204.     if (fstat(arcfile,&arcstat)!=0) error(1,ERR_STAT,arcname);
  205.     arcsize=arcstat.st_size;
  206.     if (read(arcfile,id,2)!=2 || id[0]!='H' || id[1]!='A') {
  207.         error(1,ERR_NOHA,arcname);
  208.     }
  209.     arccnt=(unsigned)getvalue(2);
  210.     arcsize=arc_scan();
  211.     if (!quiet) printf("\nArchive : %s (%d files)\n",arcname,arccnt);
  212.     }
  213.     else if ((mode&ARC_NEW) && (arcfile=open(arcname,AC_FLAGS))>=0) {
  214.     if (fstat(arcfile,&arcstat)!=0) error(1,ERR_STAT,arcname);
  215.     if (!quiet) printf("\nNew archive : %s\n",arcname);
  216.     if (write(arcfile,"HA\000",4)!=4) error(1,ERR_WRITE,arcname);
  217.     arccnt=0;
  218.     arcsize=4;
  219.     }
  220.     else error(1,ERR_ARCOPEN,arcname);
  221.     cu_add(CU_FUNC,arc_close);
  222. }
  223.  
  224. void arc_reset(void) {            
  225.  
  226.     nextheader=4;
  227. }
  228.  
  229. Fheader *arc_seek(void) {
  230.  
  231.     static Fheader *hd;
  232.     
  233.     for (;;) {
  234.     if (nextheader>=arcsize) return NULL;
  235.     if (lseek(arcfile,nextheader,SEEK_SET)<0) 
  236.       error(1,ERR_SEEK,"arc_seek()");
  237.     hd=getheader();
  238.     thisheader=nextheader;
  239.     nextheader+=hd->clen+hd->mylen;
  240.     if (hd->ver==0xff) dirty=1;
  241.     else if (match(hd->path,hd->name)) return hd;
  242.     }
  243. }
  244.  
  245. void arc_delete(void) {
  246.     
  247.     if (lseek(arcfile,thisheader,SEEK_SET)<0) 
  248.       error(1,ERR_SEEK,"arc_delete()");    
  249.     if (write(arcfile,"\xff",1)!=1) error(1,ERR_WRITE,arcname);
  250.     if (lseek(arcfile,2,SEEK_SET)<0) error(1,ERR_SEEK,"arc_delete()");    
  251.     putvalue(--arccnt,2);    
  252.     dirty=1;
  253. }
  254.  
  255. void arc_newfile(char *mdpath, char *name) {
  256.     
  257.     newhdr.ver=MYVER;
  258.     newhdr.olen=md_curfilesize();
  259.     newhdr.time=md_curfiletime();
  260.     newhdr.path=md_tohapath(mdpath);
  261.     newhdr.name=name;
  262.     newhdr.mdilen=md_newfile();
  263.     newhdr.mylen=newhdr.mdilen+20+strlen(newhdr.path)+strlen(newhdr.name);
  264.     bestpos=trypos=arcsize+newhdr.mylen;
  265.     addtries=0;
  266.     dirty|=2;
  267. }
  268.  
  269. void arc_accept(int method) {
  270.  
  271.     bestpos=trypos;
  272.     newhdr.type=method;
  273.     trypos+=newhdr.clen=ocnt;
  274.     newhdr.crc=getcrc();
  275. }
  276.  
  277. void arc_trynext(void) {
  278.  
  279.     if (lseek(arcfile,trypos,SEEK_SET)<0) error(1,ERR_SEEK,"arc_trynext()");
  280.     if (addtries++) dirty=1;
  281. }
  282.  
  283. static void delold(void) {
  284.  
  285.     U32B pos,oldpos;
  286.     unsigned i;
  287.     Fheader *hd;
  288.     
  289.     pos=4;
  290.     for (i=arccnt;i>0;--i) {
  291.     if (pos>=arcsize) break;
  292.     if (lseek(arcfile,pos,SEEK_SET)<0) error(1,ERR_SEEK,"delold()");
  293.     hd=getheader();
  294.     oldpos=pos;
  295.     pos+=hd->clen+hd->mylen;
  296.     if (hd->ver==0xff) {
  297.         dirty=1;
  298.         ++i;
  299.     }
  300.     else {
  301.         if (!strcmp(md_strcase(hd->path),newhdr.path) && 
  302.         !strcmp(md_strcase(hd->name),newhdr.name)) {
  303.         if (lseek(arcfile,oldpos,SEEK_SET)<0) 
  304.           error(1,ERR_SEEK,"delold()");
  305.         if (write(arcfile,"\xff",1)!=1) error(1,ERR_WRITE,arcname);
  306.         dirty=1;
  307.         --arccnt;
  308.         }
  309.     }
  310.     }
  311. }
  312.  
  313. int arc_addfile(void) {
  314.     
  315.     U32B basepos,len;
  316.     int cplen;
  317.     
  318.     if ((basepos=arcsize+newhdr.mylen)!=bestpos) {
  319.     if (lseek(arcfile,basepos,SEEK_SET)<0) 
  320.       error(1,ERR_SEEK,"arc_addfile()");
  321.     len=newhdr.clen;
  322.     while (len) {
  323.         if (lseek(arcfile,bestpos,SEEK_SET)<0) 
  324.           error(1,ERR_SEEK,"arc_addfile()");
  325.         cplen=BLOCKLEN>len?(int)len:BLOCKLEN;
  326.         if (read(arcfile,ib,cplen)!=cplen) error(1,ERR_READ,arcname);
  327.         len-=cplen;
  328.         bestpos+=cplen;
  329.         if (lseek(arcfile,basepos,SEEK_SET)<0) 
  330.           error(1,ERR_SEEK,"arc_addfile()");
  331.         if (write(arcfile,ib,cplen)!=cplen) error(1,ERR_WRITE,arcname);
  332.         basepos+=cplen;
  333.     }
  334.     }
  335.     if (lseek(arcfile,arcsize,SEEK_SET)<0) error(1,ERR_SEEK,"arc_addfile()");
  336.     putheader(&newhdr);
  337.     dirty&=1;
  338.     delold();
  339.     ++arccnt;
  340.     arcsize+=newhdr.mylen+newhdr.clen;
  341.     if (lseek(arcfile,2,SEEK_SET)<0) error(1,ERR_SEEK,"arc_addfile()");
  342.     putvalue(arccnt,2);
  343.     return 1;
  344. }
  345.  
  346. int arc_adddir(void) {
  347.     
  348.     newhdr.type=M_DIR;
  349.     newhdr.olen=newhdr.clen=0;
  350.     newhdr.crc=0;
  351.     
  352.     if (lseek(arcfile,arcsize,SEEK_SET)<0) error(1,ERR_SEEK,"arc_adddir()");
  353.     putheader(&newhdr);
  354.     dirty&=1;
  355.     delold();
  356.     ++arccnt;
  357.     arcsize+=newhdr.mylen;
  358.     if (lseek(arcfile,2,SEEK_SET)<0) error(1,ERR_SEEK,"arc_adddir()");
  359.     putvalue(arccnt,2);
  360.     return 1;
  361. }
  362.  
  363. int arc_addspecial(char *fullname) {
  364.  
  365.     unsigned char *sdata;
  366.     
  367.     newhdr.type=M_SPECIAL;
  368.     newhdr.olen=newhdr.clen=md_special(fullname, &sdata);
  369.     newhdr.crc=0;
  370.     
  371.     if (lseek(arcfile,arcsize,SEEK_SET)<0) 
  372.       error(1,ERR_SEEK,"arc_addspecial()");
  373.     putheader(&newhdr);
  374.     if (newhdr.clen!=0) {
  375.     if (lseek(arcfile,arcsize+newhdr.mylen,SEEK_SET)<0) 
  376.       error(1,ERR_SEEK,"arc_addspecial()");
  377.     if (write(arcfile,sdata,newhdr.clen)!=newhdr.clen) 
  378.       error(1,ERR_WRITE,arcname);
  379.     }
  380.     dirty&=1;
  381.     delold();
  382.     ++arccnt;
  383.     arcsize+=newhdr.mylen+newhdr.clen;
  384.     if (lseek(arcfile,2,SEEK_SET)<0) error(1,ERR_SEEK,"arc_addspecial()");
  385.     putvalue(arccnt,2);
  386.     return 1;
  387. }
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.